import os
import re
import inspect
from typing import List, Callable, Optional
from .logger import get_default_logger


class Config:
    """安全配置 - 20行解决所有配置需求"""

    def __init__(self, host="127.0.0.1", port=8000, debug=False, json_provider="auto"):
        self.host = host
        self.port = port
        self.debug = debug

        # 安全默认值！
        self.secret_key = os.urandom(32).hex()
        self.cors_origins = []  # 默认不允许跨域
        self.ssl_required = not debug  # 生产环境强制HTTPS
        
        # JSON配置 - 可替换的JSON库支持
        self.json_provider = json_provider  # "auto", "standard", "orjson"
        
        # 初始化JSON管理器
        from .json_utils import set_json_provider
        set_json_provider(json_provider)
    
    @property
    def json_info(self):
        """获取当前JSON配置信息"""
        from .json_utils import get_json_info
        return get_json_info()


class Route:
    """统一路由 - HTTP和WebSocket使用相同结构"""

    def __init__(
        self, path: str, handler: Callable, methods: List[str], websocket: bool
    ):
        self.path = path
        self.handler = handler
        self.methods = methods
        self.websocket = websocket
        # 简单的路由模式匹配，没有复杂的预编译
        pattern = path.replace("{", "(?P<").replace("}", ">[^/]+)")
        # 确保完全匹配，添加 $ 结束符
        if not pattern.endswith('$'):
            pattern += '$'
        self.pattern = re.compile(pattern)


class GuaApp:
    """极简应用类 - 50行解决所有问题"""

    def __init__(self, config: Optional[Config] = None):
        self.config = config or Config()
        self.routes: List[Route] = []
        self.middlewares: List[Callable] = []
        self.state: dict = {}

    def route(self, path: str, methods: Optional[List[str]] = None):
        """HTTP路由装饰器"""
        return self._add_route(path, methods or ["GET"], websocket=False)

    def websocket(self, path: str):
        """WebSocket路由装饰器"""
        return self._add_route(path, [], websocket=True)

    def use(self, middleware: Callable):
        """添加中间件"""
        self.middlewares.append(middleware)
    
    def middleware(self, func: Callable) -> Callable:
        """中间件装饰器"""
        self.use(func)
        return func

    def _add_route(self, path: str, methods: List[str], websocket: bool):
        """添加路由的内部方法"""

        def decorator(handler: Callable):
            route = Route(path, handler, methods, websocket)
            self.routes.append(route)
            return handler

        return decorator

    async def __call__(self, scope: dict, receive: Callable, send: Callable):
        """ASGI入口点 - 统一处理所有协议"""
        try:
            # 处理 ASGI Lifespan 协议
            if scope["type"] == "lifespan":
                await self._handle_lifespan(receive, send)
                return
                
            route = self._find_route(scope)
            if route:
                # 创建ASGI适配器
                asgi_handler = self._create_asgi_adapter(route.handler)
                handler = self._apply_middlewares(asgi_handler)
                await handler(scope, receive, send)
            else:
                await self._send_404(send, scope)
        except Exception as e:
            await self._send_error(e, send, scope)

    def _find_route(self, scope: dict) -> Optional[Route]:
        """查找路由 - 统一HTTP/WebSocket"""
        path = scope["path"]
        method = scope.get("method", "GET")
        is_websocket = scope["type"] == "websocket"

        for route in self.routes:
            if route.websocket == is_websocket:
                # 对于WebSocket，不需要检查method
                if is_websocket or method in route.methods:
                    match = route.pattern.match(path)
                    if match:
                        scope["path_params"] = match.groupdict()
                        return route
        return None

    def _create_asgi_adapter(self, handler: Callable) -> Callable:
        """创建ASGI适配器 - 统一处理器签名"""
        async def asgi_adapter(scope: dict, receive: Callable, send: Callable):
            # WebSocket特殊处理
            if scope.get("type") == "websocket":
                try:
                    # 检查处理器签名
                    sig = inspect.signature(handler)
                    params = {}

                    # 添加路径参数
                    params.update(scope.get("path_params", {}))

                    # 添加scope, receive, send参数
                    if "scope" in sig.parameters:
                        params["scope"] = scope
                    if "receive" in sig.parameters:
                        params["receive"] = receive
                    if "send" in sig.parameters:
                        params["send"] = send

                    # 检查处理器是否接受参数
                    if len(sig.parameters) == 0:
                        # 无参数处理器，直接调用
                        result = await handler()
                    else:
                        # 有参数处理器，传递参数
                        result = await handler(**params)

                    # WebSocket处理器不应该有返回值
                    return
                except Exception as e:
                    logger = get_default_logger()
                    logger.error(
                        "WebSocket处理器发生错误，正在关闭连接",
                        event="websocket_handler_error",
                        error=str(e),
                        error_type=type(e).__name__,
                        user_impact="用户的WebSocket连接将被关闭"
                    )
                    # WebSocket错误处理
                    try:
                        await send({
                            "type": "websocket.close",
                            "code": 1011,
                            "reason": str(e)
                        })
                    except Exception as e2:
                        logger.error(
                            "无法发送WebSocket关闭消息",
                            event="websocket_close_failed",
                            original_error=str(e),
                            close_error=str(e2),
                            user_impact="用户可能看到连接异常中断"
                        )
                    return
            
            # HTTP处理
            try:
                # 检查处理器签名
                sig = inspect.signature(handler)
                params = {}

                # 添加路径参数
                params.update(scope.get("path_params", {}))

                # 添加request参数
                if "request" in sig.parameters:
                    params["request"] = Request(scope, receive)

                # 添加scope, receive, send参数
                if "scope" in sig.parameters:
                    params["scope"] = scope
                if "receive" in sig.parameters:
                    params["receive"] = receive
                if "send" in sig.parameters:
                    params["send"] = send

                # 检查处理器是否接受参数
                if len(sig.parameters) == 0:
                    # 无参数处理器，直接调用
                    result = await handler()
                else:
                    # 有参数处理器，传递参数
                    result = await handler(**params)

                # 自动处理返回值
                if result is not None:
                    # 延迟导入避免循环依赖 - 这是必要的特殊情况
                    from .response import Response, StreamResponse, SSEResponse

                    # 检查是否为async generator（流式响应）
                    if inspect.isasyncgen(result):
                        from .response import Stream
                        response = Stream(result)
                    elif not isinstance(result, (Response, StreamResponse, SSEResponse)):
                        response = Response(result)
                    else:
                        response = result
                    await response.send(send)
            except Exception as e:
                # HTTP错误处理
                await self._send_error(e, send, scope)
        
        return asgi_adapter

    def _apply_middlewares(self, handler: Callable) -> Callable:
        """应用中间件 - 简单的装饰器链"""
        result = handler
        
        # 反向应用中间件，形成正确的调用链
        for middleware in reversed(self.middlewares):
            # 所有中间件都必须接受handler参数
            result = middleware(result)
        
        return result

    async def _send_404(self, send: Callable, scope: dict = None):
        """发送404响应"""
        try:
            # 检查是否为WebSocket连接
            if scope and scope.get("type") == "websocket":
                # WebSocket 404：发送close消息
                await send({
                    "type": "websocket.close",
                    "code": 1008,  # 策略违规
                    "reason": "WebSocket route not found"
                })
            else:
                # HTTP 404：发送HTTP错误响应
                from .sender import send_error
                await send_error(send, "Not Found", 404)
        except Exception as e:
            logger = get_default_logger()
            logger.error(
                "发送404响应失败",
                event="404_response_send_failed",
                error=str(e),
                error_type=type(e).__name__,
                user_impact="用户可能看到连接错误而不是404页面"
            )

    async def _send_error(self, error: Exception, send: Callable, scope: dict = None):
        """发送错误响应"""
        try:
            # 检查是否为WebSocket连接
            if scope and scope.get("type") == "websocket":
                # WebSocket错误：发送close消息
                await send({
                    "type": "websocket.close",
                    "code": 1011,  # 内部错误
                    "reason": str(error)
                })
            else:
                # HTTP错误：发送HTTP错误响应
                from .sender import send_error
                await send_error(send, str(error), 500)
        except Exception as e:
            logger = get_default_logger()
            logger.error(
                "发送错误响应失败",
                event="error_response_send_failed",
                error=str(e),
                error_type=type(e).__name__,
                user_impact="用户可能看到连接错误而不是错误页面"
            )

    async def _handle_lifespan(self, receive: Callable, send: Callable):
        """处理 ASGI Lifespan 协议 - 应用启动和关闭事件"""
        try:
            while True:
                message = await receive()
                if message["type"] == "lifespan.startup":
                    # 应用启动事件
                    # 这里可以添加数据库连接、缓存预热等初始化逻辑
                    await send({"type": "lifespan.startup.complete"})
                elif message["type"] == "lifespan.shutdown":
                    # 应用关闭事件
                    # 这里可以添加清理资源、关闭连接等逻辑
                    await send({"type": "lifespan.shutdown.complete"})
                    return
        except Exception as e:
            # Lifespan 协议错误处理
            await send({
                "type": "lifespan.startup.failed" if "startup" in str(e) else "lifespan.shutdown.failed",
                "message": str(e)
            })


class Request:
    """简化的请求对象 - 添加流式支持"""

    def __init__(self, scope: dict, receive: Callable):
        self.scope = scope
        self.receive = receive
        self.method = scope.get("method", "GET")
        self.path = scope.get("path", "/")  # 提供默认值
        self.query_string = scope.get("query_string", b"").decode()
        
        # 流式请求相关属性
        self._body_stream = None
        self._content_length = self._get_content_length()
        
    def _get_content_length(self):
        """获取内容长度"""
        headers = dict(self.scope.get("headers", []))
        length = headers.get(b"content-length", b"0").decode()
        try:
            return int(length)
        except:
            return 0
            
    @property
    def is_streaming(self):
        """检测是否为流式请求"""
        # 大文件或chunked编码
        return self._content_length > 1024 * 1024 or self._is_chunked()
        
    def _is_chunked(self):
        """检测是否为chunked编码"""
        headers = dict(self.scope.get("headers", []))
        encoding = headers.get(b"transfer-encoding", b"").decode().lower()
        return "chunked" in encoding
        
    async def stream_body(self, chunk_size=8192):
        """流式读取请求体 - async generator"""
        if self._body_stream is None:
            self._body_stream = self._create_body_stream()
            
        async for chunk in self._body_stream:
            yield chunk
            
    async def _create_body_stream(self):
        """创建体流"""
        received = 0
        
        while True:
            message = await self.receive()
            
            if message["type"] == "http.request":
                chunk = message.get("body", b"")
                if not chunk:
                    if message.get("more_body", False):
                        continue
                    else:
                        break
                        
                yield chunk
                received += len(chunk)
                
                # 检查是否接收完毕
                if not message.get("more_body", False):
                    break
                    
            elif message["type"] == "http.disconnect":
                # 客户端断开连接
                break
